/*
 * Copyright (c) 2011, Andrea Palloni
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 * - Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 * - Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 * - Neither the name of the copyright holder nor the names of its contributors may be used
 * 	  to endorse or promote products derived from this software without specific prior written
 *    permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
package net.palla.biblio.client;

import java.util.List;

import net.palla.biblio.shared.Cdd;

import com.google.gwt.cell.client.AbstractCell;
import com.google.gwt.cell.client.Cell;
import com.google.gwt.cell.client.FieldUpdater;
import com.google.gwt.cell.client.HasCell;
import com.google.gwt.core.client.GWT;
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.view.client.AsyncDataProvider;
import com.google.gwt.view.client.DefaultSelectionEventManager;
import com.google.gwt.view.client.HasData;
import com.google.gwt.view.client.Range;
import com.google.gwt.view.client.SelectionModel;
import com.google.gwt.view.client.TreeViewModel;

public class CddTreeViewModel implements TreeViewModel {
	
	//see http://code.google.com/webtoolkit/doc/latest/DevGuideUiCellWidgets.html#celltree
	//In addition to a cell, a node also has a DataProvider, 
	//	to provide the data to the children of the NodeInfo, and a SelectionModel,
	//	to indicate how it can be selected by the user.

	//When a node is opened, CellTree will call getNodeInfo() on TreeViewModel 
	//	to get the NodeInfo used to render the children.
	
	/*
	 * Creating a CellTree:
		1.	Define a TreeViewModel and getNodeInfo
			a.	In getNodeInfo, create a data provider for the child nodes.
			b.	Populate the data provider with data.
			c.	Create a standard or custom Cell to render the children.
		2.	Create an instance of your TreeViewModel class.
		3.	Create a CellTree, passing in the TreeViewModel instance.
	 */

	private class CddCell extends AbstractCell<Cdd> implements HasCell<Cdd, Boolean> {

		@Override
		public void render(com.google.gwt.cell.client.Cell.Context context,
				Cdd value, SafeHtmlBuilder sb) {
            if (value != null) {
                sb.appendEscaped(value.getName());
              }
		}

		@Override
		public Cell<Boolean> getCell() {
			return null;
		}

		@Override
		public FieldUpdater<Cdd, Boolean> getFieldUpdater() {
			return null;
		}

		@Override
		public Boolean getValue(Cdd object) {
			return selectionModel.isSelected(object);
		}		
	}
	
	private class CddDataProvider extends AsyncDataProvider<Cdd> {

		private String parentkey;
		
		public CddDataProvider(String parentkey) {
			this.parentkey = parentkey;
		}
		@Override
		protected void onRangeChanged(HasData<Cdd> display) {
			final Range range = display.getVisibleRange();
			
			try {
				service.getCdds(parentkey, new AsyncCallback<List<Cdd>>() {

					@Override
					public void onFailure(Throwable caught) {
						GWT.log("getCdds failure", caught);
					}

					@Override
					public void onSuccess(List<Cdd> result) {
						// TODO Auto-generated method stub
						int start = range.getStart();
						if (result.size() == 0)
							updateRowData(start, null);//treat node as a leaf
						else
							updateRowData(start, result);
					}
				});
			} catch (Exception e) {
				e.printStackTrace();
				GWT.log("getCdds failure", e);
			}
		}
		
	}
	
	private final CddCell cddCell = new CddCell();
	private final SelectionModel<Cdd> selectionModel;
	private final DefaultSelectionEventManager<Cdd> selectionManager =
	      DefaultSelectionEventManager.createCheckboxManager();
	
	private BiblioServiceAsync service;
	
	public CddTreeViewModel (BiblioServiceAsync service, final SelectionModel<Cdd> selectionModel) {
		this.selectionModel = selectionModel;
		this.service = service;
	}
	
	@SuppressWarnings({ "rawtypes", "unchecked" })
	@Override
	public <T> NodeInfo<?> getNodeInfo(T value) {
		if (value == null) {
			//gets top data
			CddDataProvider dataProvider = new CddDataProvider(null);			
			// Return a node info that pairs the data with a cell.
		    return new DefaultNodeInfo(dataProvider, cddCell, selectionModel, selectionManager, null);
		}
		Cdd parent = (Cdd) value;
		//gets top data
		CddDataProvider dataProvider = new CddDataProvider(parent.getId());			
		// Return a node info that pairs the data with a cell.
	    return new DefaultNodeInfo(dataProvider, cddCell, selectionModel, selectionManager, null);
	}

	@Override
	public boolean isLeaf(Object value) {
		return false;
	}

}
